<template>
  <el-cascader
    v-bind="$myProps"
    v-on="$myListeners"
    :options="myOptions"
    v-model="currentValue"
    @change="handleChange"
  ></el-cascader>
</template>

<script>
export default {
  props: {
    //选中项绑定值
    value: [String, Number, Boolean, Array],
    //可选项数据源，键名可通过 Props 属性配置
    options: {
      type: Array,
      required: true,
    },
    enableRootEmptyChild: {
      type: Boolean,
      default: true,
    },
    //简单值，非递进式数组
    enableSingleValue: {
      type: Boolean,
      default: true,
    },
    //排除不显示的项
    exceptionOptionValues: {
      type: [String, Number, Array],
      default() {
        return [];
      },
    },
  },
  data() {
    return {
      currentValue: [],
      hashData: {},
      //选项数据
      optionsData: [],
    };
  },
  watch: {
    //选项更新
    options: {
      immediate: true,
      handler(newValue) {
        this.setOptions();
      },
    },
    //选中值发生变化时
    currentValue(newValue, oldValue) {
      if (JSON.stringify(newValue) != JSON.stringify(oldValue)) {
        this.$emit("input", this.emitValue(newValue));
      }
    },
    //设定值发生变化时
    value: {
      immediate: true,
      handler(newValue, oldValue) {
        console.log(newValue)
        if (JSON.stringify(newValue) != JSON.stringify(oldValue)) {
          this.setCurrentValue(newValue);
        }
      },
    },
  },
  computed: {
    $myProps() {
      let myProps = this.$public.inheritProps(this);

      this.$delete(myProps, "value");

      return myProps;
    },
    $myListeners() {
      let myListeners = this.$public.inheritListeners(this);

      this.$delete(myListeners, "input");

      return myListeners;
    },
    myProps() {
      return Object.assign(
        {
          //次级菜单的展开方式,click / hover
          expandTrigger: "click",
          //是否多选
          multiple: false,
          //是否严格的遵守父子节点不互相关联
          checkStrictly: true,
          //在选中节点改变时，是否返回由该节点所在的各级菜单的值所组成的数组，若设置 false，则只返回该节点的值
          emitPath: true,
          //是否动态加载子节点，需与lazyLoad方法结合使用
          lazy: false,
          //加载动态数据的方法，仅在 lazy 为 true 时有效
          lazyLoad: function (node, resolve) {
            //node为当前点击的节点，resolve为数据加载完成的回调(必须调用)
          },
          //指定选项的值为选项对象的某个属性值
          value: "value",
          //指定选项标签为选项对象的某个属性值
          label: "label",
          //指定选项的子选项为选项对象的某个属性值
          children: "children",
          //指定选项的禁用为选项对象的某个属性值
          disabled: "disabled",
          //指定选项的叶子节点的标志位为选项对象的某个属性值
          leaf: "leaf",
          //子从关系的父指向属性
          parentNodeKey: "ParentId",
        },
        this.$myProps.props
      );
    },
    myOptions() {
      return this.$myProps.options;
    },
    //需要排除的项列表
    exceptionOptionValuesArray() {
      return Object.prototype.toString.call(this.exceptionOptionValues) !==
        "[object Array]"
        ? [this.exceptionOptionValues]
        : this.exceptionOptionValues;
    },
  },
  methods: {
    //cascader内赋值的时候触发
    emitValue(newVal) {
      let value = [].concat(newVal);

      if (this.myProps.multiple) {
        //如果是启用复选
        if (this.enableSingleValue) {
          for (var i = 0; i < value.length; i++) {
            value[i] = [].concat(value[i]).pop();
          }
        }
      } else {
        //单选
        if (this.enableSingleValue) {
          value = value.pop();
        }
      }
      return value;
    },
    //当选中节点变化时触发
    //val:选中节点的值
    handleChange(newVal) {
      this.$emit("change", this.emitValue(newVal));
    },
    //解析选项数组
    analysisOptions(paragram) {
      let { options = this.options, parentValue = null } = paragram || {};

      options = options || [];

      let fromParent = parentValue != null;

      //遍历数组
      options.forEach((item) => {
        let optionsValue = item[this.myProps.value];

        //如果存在排除的项，则跳过
        if (this.exceptionOptionValuesArray.indexOf(optionsValue) > -1) {
          return;
        }

        this.hashData[optionsValue] = item;

        if (fromParent == true) {
          item[this.myProps.parentNodeKey] = parentValue;
        }

        //存在children，则继续遍历，填充hashData
        if (
          Object.prototype.toString.call(item[this.myProps.children]) ===
            "[object Array]" &&
          item[this.myProps.children].length > 0
        ) {
          if (fromParent != true) {
            this.optionData.push(item);
          }

          this.analysisOptions({
            options: item[this.myProps.children],
            parentValue: item[this.myProps.value],
          });
        } else if (fromParent != true) {
          if (
            item[this.myProps.parentNodeKey] == 0 ||
            item[this.myProps.parentNodeKey] == "0" ||
            item[this.myProps.parentNodeKey] == "" ||
            item[this.myProps.parentNodeKey] === undefined
          ) {
            if (
              this.enableRootEmptyChild == false &&
              item[this.myProps.children] === undefined
            ) {
              item[this.myProps.children] = [];
            }

            this.optionData.push(item);
          } else {
            let hashKey = item[this.myProps.parentNodeKey];

            if (this.hashData[hashKey]) {
              this.hashData[hashKey][this.myProps.children] =
                this.hashData[hashKey][this.myProps.children] || [];

              if (
                this.hashData[hashKey][this.myProps.children].indexOf(item) ==
                -1
              ) {
                this.hashData[hashKey][this.myProps.children].push(item);
              }
            }
          }
        }
      });
    },
    setOptions() {
      this.hashData = {};
      this.optionData = [];
      this.analysisOptions();
      this.setCurrentValue();
    },
    createFullValue(newVal) {
      let hashData = this.hashData;
      let value = [newVal];

      //循环遍历，判断父级菜单存不存在
      let parentValue =
        (hashData[newVal] && hashData[newVal][this.myProps.parentNodeKey]) ||
        "";
      while (parentValue != "" && parentValue != "0") {
        value.unshift(parentValue);
        parentValue =
          (hashData[parentValue] &&
            hashData[parentValue][this.myProps.parentNodeKey]) ||
          "";
      }

      return value;
    },
    //拼装组成递进式值数组
    pieceValue(newVal) {
      var value = [];

      let hashData = this.hashData;
      value = [newVal];

      //循环遍历，判断父级菜单存不存在
      let parentValue =
        (hashData[newVal] && hashData[newVal][this.myProps.parentNodeKey]) ||
        "";

      while (parentValue != "" && parentValue != "0") {
        value.unshift(parentValue);
        parentValue =
          (hashData[parentValue] &&
            hashData[parentValue][this.myProps.parentNodeKey]) ||
          "";
      }

      return value;
    },
    //设置当前选择的值
    setCurrentValue(newVal) {
      newVal = newVal || this.value;

      let value = [];

      //复选
      if (this.myProps.multiple) {
        if (Object.prototype.toString.call(newVal) != "[object Array]") {
          newVal = [newVal];
        }

        //复选功能，遍历初始值
        newVal.forEach((val) => {
          if (Object.prototype.toString.call(val) != "[object Array]") {
            val = this.pieceValue(val);
          }

          value.push(val);
        });
      }
      //单选
      else {
        if (this.enableSingleValue) {
          value = this.pieceValue(newVal);
        } else {
          if (Object.prototype.toString.call(newVal) != "[object Array]") {
            value = [newVal];
          }

          value = newVal;
        }
      }
      console.log(value,111)
      this.currentValue = value;
    },
  },
  mounted() {
    this.$emit("mounted");
  },
  created() {
    this.$emit("created", {
      createFullValue: this.createFullValue,
    });
  },
};
</script>
<style scoped>
.el-cascader {
  width: 100%;
}
</style>